const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const schedule = require('node-schedule');
const cors = require('koa2-cors');
const CryptoJS = require('crypto-js');
const dayjs = require('dayjs');
require('dotenv').config();
const router = require('./routes');
const connectDB = require('./config/db');
const { generatePredictions } = require('./method');
const {
    getWeekPrice,
    calculateLowPrice,
    calculateHighPrice
} = require('./method/buySellPrice');
const {
    updateCache,
    getCache,
    updateConceptHistoryCache
} = require('./controllers/cachedController');
const { getStockList, getAllStock } = require('./controllers/stockController');
const {
    findByDate,
    create,
    update,
    delete: deleteHistory
} = require('./controllers/historyController');
// 初始化数据库
connectDB();

// 中间件，用于验证 MD5 签名
const verifyMD5Signature = async (ctx, next) => {
    const { authorization } = ctx.request.header;
    if (!authorization) {
        ctx.status = 400;
        ctx.body = { error: 'Missing data or authorization' };
        return;
    }
    // 重新计算签名
    const newSignature = CryptoJS.MD5('renser_ying_guang_me').toString();
    if (newSignature !== authorization) {
        ctx.status = 401;
        ctx.body = { error: 'Invalid authorization' };
        return;
    }
    await next();
};

const app = new Koa();
// 中间件
// app.use(cors({
//     origin: 'http://182.92.203.127/'
// }));
app.use(cors());
app.use(verifyMD5Signature);
app.use(async (ctx, next) => {
    ctx.set(
        'Access-Control-Allow-Headers',
        'authorization,content-type,token,identify'
    );
    try {
        await next();
    } catch (err) {
        console.error('服务器出错了');
    }
});
app.use(bodyParser());
app.use(router.routes()).use(router.allowedMethods());

const PORT = process.env.PORT || 3000;
const server = app.listen(PORT, '0.0.0.0', () => {
    console.log(`服务启动 ${PORT}`);
});

const updateCurrentPredictions = async () => {
    let stocks = getCache();
    let predictionStocks = stocks
        .filter((p) => p.predictionScore >= 65)
        .sort((a, b) => b.predictionScore - a.predictionScore);
    const todayPrediction = await findByDate(dayjs());
    const currentTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
    const mergedPredictions = [...todayPrediction];
    predictionStocks.forEach((item) => {
        const existIndex = mergedPredictions.findIndex((r) => r.code === item.code);
        if (existIndex < 0) {
            mergedPredictions.push({
                ...item,
                // 预测时间
                predictionTime: currentTime,
                // 预测时价格
                predictedPrice: item.price
            });
        } else {
            const existItem = mergedPredictions[existIndex];

            mergedPredictions[existIndex] = {
                ...existItem,
                price: item.price,
                mainMoneyNet: item.mainMoneyNet
            };
        }
    });

    mergedPredictions.forEach((item) => {
        if (item._id) {
            update(item._id, item);
        } else {
            create(item);
        }
    });
};

// 定时任务：工作日每5分钟更新数据
server.on('listening', () => {
    const rule = new schedule.RecurrenceRule();
    rule.dayOfWeek = [new schedule.Range(1, 5)];
    rule.hour = [9, 10, 11, 13, 14];
    // rule.minute = new schedule.Range(0, 59);
    // rule.second = [0, 30];
    rule.minute = [8, 17, 28, 38, 49, 59];
    rule.second = [0];

    schedule.scheduleJob(rule, async () => {
        try {
            const stocks = await getStockList(56);
            console.log(
                `${dayjs().format('YYYY-MM-DD HH:mm:ss')}总数`,
                stocks.length
            );
            if (stocks.length > 0) {
                // 评分后的数据
                const predictionStocks = await generatePredictions(stocks);
                updateCache(predictionStocks);
                // 更新当前预测数据
                updateCurrentPredictions();
            }
        } catch (error) {
            console.error(`获取全部数据失败`);
        }
    });

    // 每周一至周五的8:01:00执行 记录历史概念信息
    schedule.scheduleJob('0 1 8 ? * MON-FRI', async () => {
        updateConceptHistoryCache();
    });

    // 每周一至周五的8:00:00执行 获取周价
    // schedule.scheduleJob('0 1,7 8 ? * MON-FRI', async () => {
    //     getWeekPrice();
    // });
    // 每周一至周五的8:00:00执行 获取百日最低价
    // schedule.scheduleJob('0 1,9,17 8 ? * MON-FRI', async () => {
    //     calculateLowPrice();
    // });
    // 每周一至周五的8:20:00执行 获取百日最高价
    // schedule.scheduleJob('0 25,34,41 8 ? * MON-FRI', async () => {
    //     calculateHighPrice();
    // });

    // 每天9点删除30天前的数据
    schedule.scheduleJob('0 0 9 ? * *', async () => {
        try {
            let monthDay = dayjs().subtract(30, 'day').format('YYYY-MM-DD');
            const monthPrediction = await findByDate(monthDay);
            console.log(
                `每天9点删除前30天的历史量化数据，删除${monthDay}条数为：`,
                monthPrediction.length
            );
            monthPrediction.forEach((item) => {
                deleteHistory(item._id);
            });
        } catch (error) {
            console.error(`删除${monthDay}数据失败`);
        }
    });
});
